Inside Macintosh: Imaging with QuickDraw

Previous | Chapter Top | Chapter Contents | Next

Saving Pictures

After creating or changing pictures, your application should allow the user to save them. To save a picture in a 'PICT' file, you should use File Manager routines, such as FSpCreate , FSpOpenDF , FSWrite , and FSClose . The use of these routines is illustrated in Listing 7-9 , and they are described in detail in the chapter "File Manager" in Inside Macintosh: Files . Remember that the first 512 bytes of a 'PICT' file are reserved for your application's own purposes. As shown in Listing 7-9 , your application should store the data (that is, the Picture record) after this 512-byte header.

Listing 9 Saving a picture as a 'PICT' file

FUNCTION DoSavePICTAsCmd(picH: PicHandle): OSErr;
LABEL 8,9;
VAR
    myReply:                                StandardFileReply;
    err, ignore:                            OSErr;
    pictFileRefNum:                         Integer;
    dataLength, zeroData, count:            LongInt;
BEGIN                       {display the default Save dialog box}
    StandardPutFile('Save picture as:','untitled',myReply);
    err := noErr;       {return noErr if the user cancels}
    IF myReply.sfGood THEN
    BEGIN
        IF NOT myReply.sfReplacing THEN             {create the file if it doesn't exist}
            err := FSpCreate(myReply.sfFile,'WAVE','PICT',smSystemScript);
        IF err <> noErr THEN GOTO 9;
        err := FSpOpenDF(myReply.sfFile,fsRdWrPerm,pictFileRefNum);                     {open file}
        IF err <> noErr THEN GOTO 8;
        zeroData := 0;
        dataLength := 4;
        FOR count := 1 TO 512 DIV dataLength DO                 {write the PICT file header}
            err := FSWrite(pictFileRefNum,dataLength,
                                @zeroData);     {for this app, put 0's in header}
        IF err <> noErr THEN GOTO 8;
        dataLength := GetHandleSize(Handle(picH));
        HLock(Handle(picH));        {lock picture handle before writing data}
        err := FSWrite(pictFileRefNum,dataLength,Ptr(picH^));                   {write picture }
                                                                                { data to file}
         HUnlock(Handle(picH));         {unlock picture handle after writing data}
    END;
    8:
        ignore := FSClose(pictFileRefNum);              {close the file}
    9:
        DoSavePICTAsCmd := err;
END;

To save a picture in a 'PICT' resource, you should use Resource Manager routines, such as FSpOpenResFile (to open your application's resource fork), ChangedResource (to change an existing 'PICT' resource), AddResource (to add a new 'PICT' resource), WriteResource (to write the data to the resource), and CloseResFile and ReleaseResource (to conclude saving the resource). These routines are described in the chapter "Resource Manager" in Inside Macintosh: More Macintosh Toolbox .

To place a picture in the scrap--for example, in response to the user choosing the Copy command to copy a picture to the Clipboard--use the Scrap Manager function PutScrap , which is described in the chapter "Scrap Manager" in Inside Macintosh: More Macintosh Toolbox .

For large 'PICT' files, it is useful to spool the picture data to disk instead of writing it all directly into memory. In low-memory conditions, for example, your application might find it useful to create a temporary file on disk for storing drawing instructions; your application can read this information as necessary. The application-defined routine MyReplacePutPic shown in Listing 7-10 replaces the putPicProc field of the current graphics port's CQDProcs record with an application-defined low-level routine, called MyFilePutPic . While QuickDraw's standard StdPutPic procedure writes picture data to memory, MyFilePutPic writes the picture data to disk. ( Listing 7-3 shows how to replace QuickDraw's standard StdGetPic procedure with one that reads data from a spool file.)

Listing 10 Replacing QuickDraw's standard low-level picture-writing routine

FUNCTION MyReplacePutPic: QDProcsPtr;
VAR
    currPort:           GrafPtr;
    customProcs:        QDProcs;
    customCProcs:       CQDProcs;
    savedProcs:         QDProcsPtr;
BEGIN
    GetPort(currPort);
    savedProcs := currPort^.grafProcs;              {save QDProcs or CQDProcs record }
                                                    { for current graphics port}
    IF MyIsColorPort(currPort) THEN             {see Listing 7-4}
    BEGIN
        SetStdCProcs(customCProcs);             {create new CQDProcs record containing }
                                                { standard Color QuickDraw low-level }
                                                { routines}

        customCProcs.putPicProc := @MyFilePutPic;               {replace StdPutPic with }
                                                                { address of custom }
                                                                { low-level routine }
                                                                { shown in Listing 7-11}
        currPort^.grafProcs := @customCProcs;               {replace current CQDProcs}
    END
    ELSE
    BEGIN           {perform similar work for a basic graphics port}
        SetStdProcs(customProcs);
        customProcs.putPicProc := @MyFilePutPic;
        currPort^.grafProcs := @customProcs;
    END;
    gPictureSize := 0;          {track the picture size}
    gSpoolPicture := PicHandle(NewHandle(0));
    MyReplacePutPic := savedProcs;                      {return saved CQDProcs or QDProcs }
                                                { record for restoring at a later time}
END;

Listing 7-11 shows MyFilePutPic , which uses the File Manager function FSWrite to write picture data to the file with the file reference number assigned to the application-defined global variable gPictFileRefNum . Your application does not keep track of where FSWrite stops or resumes writing a file. After writing a portion of a file, FSWrite automatically handles where to begin writing next.

Listing 11 A custom low-level routine for spooling a picture to disk

PROCEDURE MyFilePutPic (dataPtr: Ptr; byteCount: Integer);
VAR
    dataLength: LongInt;
    myErr: OSErr;
BEGIN
    dataLength := byteCount;
    gPictureSize := gPictureSize + byteCount;
    myErr := FSWrite(gPictFileRefNum, dataLength, dataPtr);
    IF gSpoolPicture <> NIL THEN
    gSpoolPicture^^.picSize := gPictureSize;
END;

© 1997 Apple Computer, Inc.

Previous | Chapter Top | Chapter Contents | Next